//
//  STUserService.swift
//  Story
//
//  Created by 汤泽川 on 2019/4/2.
//  Copyright © 2019 汤泽川. All rights reserved.
//

import Foundation
import RxSwift
import RxCocoa

class STUserService : NSObject {
    
    static let shareInstance = STUserService()
    private let STUserAccessTokenStoreKey = "STUserAccessTokenStoreKey"
    private let STUserInfoStoreKey = "STUserInfoStoreKey"
    private(set) var accessToken : String?
    public let currentUser = BehaviorRelay<STUserInfo?>(value: nil)

    private override init() {
        accessToken = UserDefaults.standard.string(forKey: STUserAccessTokenStoreKey)
        let userData = UserDefaults.standard.data(forKey: STUserInfoStoreKey)
        if userData != nil {
            currentUser.accept(try? JSONDecoder().decode(STUserInfo.self, from: userData!))
        }
    }
    
    public func updateUser(newUser : STUserInfo) {
        let userData = try? JSONEncoder().encode(newUser)
        if userData != nil {
            UserDefaults.standard.set(userData, forKey: STUserInfoStoreKey)
        }
        currentUser.accept(newUser)
    }
    
    private func storeLoginUserInfo(loginInfo : LoginResponseModel) {
        UserDefaults.standard.set(loginInfo.accessToken, forKey: STUserAccessTokenStoreKey)
        accessToken = loginInfo.accessToken
        updateUser(newUser: loginInfo.userInfo)
    }
    
    private func deleteLocalUser() {
        UserDefaults.standard.set(nil, forKey: STUserInfoStoreKey)
        UserDefaults.standard.set(nil, forKey: STUserAccessTokenStoreKey)
        accessToken = nil
        currentUser.accept(nil)
    }
    
    @discardableResult
    public func login(username : String, password : String) -> STResponse<ResponseModel<LoginResponseModel> > {
        let response = STResponse<ResponseModel<LoginResponseModel> >()
        STUserAPI.login(username: username, password: password) { (data, error) in
            if data?.data != nil {
                self.storeLoginUserInfo(loginInfo: (data?.data)!)
            }
            response.execute(data, error)
        }
        return response
    }
    
    @discardableResult
    public func logout() -> STResponse<ResponseModel<String> > {
        let response = STResponse<ResponseModel<String> >()
        STUserAPI.logout() { (data, error) in
            if data?.isSuccess ?? false == true {
                self.deleteLocalUser()
            }
            response.execute(data, error)
        }
        return response
    }
    
    @discardableResult
    public func register(username : String, password : String, email : String, verifyCode : String) -> STResponse<ResponseModel<String> > {
        let response = STResponse<ResponseModel<String> >()
        STUserAPI.register(username: username, password: password, email: email, verifyCode: verifyCode) { (error) in
            response.execute(nil, error)
        }
        return response
    }
    
    @discardableResult
    public func resetPassword(username : String, password : String, email : String, verifyCode : String) -> STResponse<ResponseModel<String> > {
        let response = STResponse<ResponseModel<String> >()
        STUserAPI.resetPassword(username: username, password: password, email: email, verifyCode: verifyCode) { (error) in
            response.execute(nil, error)
        }
        return response
    }
    
    @discardableResult
    public func fetchUserData() -> STResponse<STUserDataModel> {
        let response = STResponse<STUserDataModel>()
        STUserAPI.quaryUserData(result: { (model, error) in
            response.execute(model?.data, error)
        })
        return response
    }
    
    @discardableResult
    public func quaryFollowStatus(targetId : Int) -> STResponse<Int> {
        let response = STResponse<Int>()
        STUserAPI.quaryFollowStatus(targetId: targetId, result: { (model, error) in
            if let dict = model?.data {
                response.execute(dict["status"], error)
            } else {
                response.execute(nil, error)
            }
        })
        return response
    }
    
    @discardableResult
    public func changeFollowStatus(targetId : Int, status : Int) -> STResponse<String> {
        let response = STResponse<String>()
        STUserAPI.changeFollowStatus(targetId: targetId, status : status, result: { (model, error) in
            response.execute(nil, error)
        })
        return response
    }
    
    @discardableResult
    public func fetchFollowList(page : Int, count : Int) -> STResponse<[STUserInfo]> {
        let response = STResponse<[STUserInfo]>()
        STUserAPI.quaryFollowList(page: page, count: count, result: { (model, error) in
            response.execute(model?.data, error)
        })
        return response
    }
    
    @discardableResult
    public func updateUserProfile(avatarImage : Data?, introduce : String?) -> STResponse<STUserInfo> {
        let response = STResponse<STUserInfo>()
        let imageObserver = PublishSubject<String?>()
        
        _ = imageObserver.subscribe(onNext: { (url) in
            STUserAPI.changeProfile(avatarUrl: url, introduce: introduce, result: { (data, error) in
                response.execute(data?.data, error)
            })
        })
        if avatarImage == nil {
            imageObserver.onNext(nil)
        } else {
            STUploadService().uploadImage(fileData: avatarImage!).result { (url, error) in
                if url != nil {
                    imageObserver.onNext(url!)
                }
                if error != nil {
                    response.execute(nil, error)
                }
            }
        }
        return response
    }
}
